#include "api_io.h"
#include "utility.h"
#include "ringbuffer.h"

static uint8_t usb_rx_buf[512], uart_rx_buf[512];
static struct ringbuffer usb_rx_rb, uart_rx_rb;

void api_io_init(void)
{
	ringbuffer_init(&usb_rx_rb, usb_rx_buf, sizeof(usb_rx_buf));
	ringbuffer_init(&uart_rx_rb, uart_rx_buf, sizeof(uart_rx_buf));
}

SIMPLE_API_FUN(io, WriteByte)
{
	simple_io_channel ch = (simple_io_channel)params[0];
	volatile uint8_t byte = params[1];
	
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:
			return ERR_MISSING_PARAMETER;
		//break;
		
		case SIMPLE_IO_CHANNEL_USB:
			ringbuffer_putchar(&usb_rx_rb, byte);
		break;
		
		case SIMPLE_IO_CHANNEL_COM1:
			ringbuffer_putchar(&uart_rx_rb, byte);
		break;
	}
	
	return ERR_NONE;
}

SIMPLE_API_FUN(io, ReadByte)
{ 
	simple_io_channel ch = (simple_io_channel)params[0];
	
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_USB:
		case SIMPLE_IO_CHANNEL_COM1:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:
			*rsp_len = 0;
		break;
	}
	
	return ERR_NONE;
}

SIMPLE_API_FUN(io, TestEmpty)
{
	simple_io_channel ch = (simple_io_channel)params[0];
	simple_io_dir dir = (simple_io_dir)params[1];
	
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_USB:
		case SIMPLE_IO_CHANNEL_COM1:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:
			rsp[0] = true;
		break;
	}
	*rsp_len = 1;
	return ERR_NONE;
}

SIMPLE_API_FUN(io, TestFull)
{
	simple_io_channel ch = (simple_io_channel)params[0];
	simple_io_dir dir = (simple_io_dir)params[1];
	
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_USB:
		case SIMPLE_IO_CHANNEL_COM1:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:
			rsp[0] = true;
		break;
	}
	*rsp_len = 1;
	return ERR_NONE;
}

SIMPLE_API_FUN(io, GetBufferSize)
{
	simple_io_channel ch = (simple_io_channel)params[0];
	simple_io_dir dir = (simple_io_dir)params[1];
	uint16_t *buffer_size = (uint16_t *)rsp;
	
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_USB:
		case SIMPLE_IO_CHANNEL_COM1:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:
			*buffer_size = 0;
		break;
	}
	*rsp_len = sizeof(uint16_t);
	return ERR_NONE;
}

SIMPLE_API_FUN(io, GetByteCount)
{
	simple_io_channel ch = (simple_io_channel)params[0];
	simple_io_dir dir = (simple_io_dir)params[1];
	uint16_t *buffer_count = (uint16_t *)rsp;
	
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_USB:
		case SIMPLE_IO_CHANNEL_COM1:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:	
			*buffer_count = 0;
		break;
	}
	*rsp_len = sizeof(uint16_t);
	return ERR_NONE;
}

SIMPLE_API_FUN(io, WriteBytes)
{
	simple_io_channel ch = (simple_io_channel)params[0];
	uint16_t *array_len = (uint16_t *)(params + 1);
	uint8_t *array = params + sizeof(uint16_t) + 1;
	uint16_t *write_len = (uint16_t *)rsp;
	
	*rsp_len = sizeof(uint16_t);
	*write_len = 0;
	
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_USB:
		case SIMPLE_IO_CHANNEL_COM1:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:
			return ERR_MISSING_PARAMETER;
		//break;
	}
	
	return ERR_NONE;
}

SIMPLE_API_FUN(io, ReadBytes)
{
	simple_io_channel ch = (simple_io_channel)params[0];
	uint16_t *max_byte = (uint16_t *)&params[1];
	uint16_t *array_len = (uint16_t *)rsp;
	uint8_t *array = rsp + sizeof(uint16_t);
	
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_USB:
		case SIMPLE_IO_CHANNEL_COM1:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:
			*array_len = 0;
		break;
	}
	
	return ERR_NONE;
}

simple_api_fun_handle api_io_list[SIMPLE_API_IO_FUN_NUM] = {
	[0x00] = SIMPLE_API_NAME(io, WriteByte),
	[0x01] = SIMPLE_API_NAME(io, ReadByte),
	[0x02] = SIMPLE_API_NAME(io, TestEmpty),
	[0x03] = SIMPLE_API_NAME(io, TestFull),
	[0x04] = SIMPLE_API_NAME(io, GetBufferSize),
	[0x05] = SIMPLE_API_NAME(io, GetByteCount),
	[0x0D] = SIMPLE_API_NAME(io, WriteBytes),
	[0x0E] = SIMPLE_API_NAME(io, ReadBytes),
};

void api_io_put(simple_io_channel ch, uint8_t *byte, uint16_t len)
{
	switch(ch)
	{
		case SIMPLE_IO_CHANNEL_NONE:
		case SIMPLE_IO_CHANNEL_USB:
		case SIMPLE_IO_CHANNEL_COM1:
		case SIMPLE_IO_CHANNEL_COM2:
		case SIMPLE_IO_CHANNEL_BLE:
			
		break;
	}
}
